home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-27 | 7.8 KB | 235 lines | [TEXT/CCL2] |
-
- ;;; Description: Convert algdata & synonym from ast to definition form.
- ;;; Lots of error checking.
-
- ;;; Algdata:
- ;;; Errors detected:
- ;;; Types & classes (deriving & context) resolved
- ;;; context tyvars must be parameters
- ;;; all parameter tyvars must be referenced
- ;;; only parameter tyvars must be referenced
-
- (define (algdata->def data-decl)
- (remember-context data-decl
- (with-slots data-decl (context simple constrs deriving annotations) data-decl
- (let* ((def (tycon-def simple))
- (tyvars (simple-tyvar-list simple))
- (enum? '#t)
- (tag 0)
- (derived-classes '())
- (tyvars-referenced '())
- (all-con-vars '())
- (all-strict? (process-alg-strictness-annotation annotations))
- (constr-defs
- (map (lambda (constr)
- (with-slots constr (constructor types) constr
- (let ((constr-def (con-ref-con constructor))
- (c-arity (length types))
- (con-vars '())
- (all-types '())
- (strictness '()))
- (when (not (eqv? c-arity 0))
- (setf enum? '#f))
- (dolist (type types)
- (let* ((ty (tuple-2-1 type))
- (anns (tuple-2-2 type))
- (tyvars1 (resolve-type ty)))
- (push ty all-types)
- (push (get-constr-strictness anns all-strict?)
- strictness)
- (dolist (v tyvars1)
- (if (not (memq v tyvars))
- (signal-bad-algdata-tyvar v)))
- (setf con-vars (append tyvars1 tyvars-referenced))
- (setf tyvars-referenced
- (append tyvars1 tyvars-referenced))))
- (push (tuple constr con-vars) all-con-vars)
- (update-slots con constr-def
- (arity c-arity)
- (types (reverse all-types))
- (tag tag)
- (alg def)
- (infix? (con-ref-infix? constructor))
- (slot-strict? (reverse strictness)))
- (incf tag)
- constr-def)))
- constrs)))
- (dolist (class deriving)
- (let* ((name (add-di-prefix (class-ref-name class)))
- (di (resolve-toplevel-name name)))
- (if (eq? di '#f)
- (recoverable-error 'unknown-deriving
- "Derivable instance ~A not known" (class-ref-name class))
- (push di derived-classes))))
- (when (not (null? constrs))
- (dolist (tyvar tyvars)
- (when (not (memq tyvar tyvars-referenced))
- (signal-unreferenced-tyvar-arg tyvar))))
- (resolve-signature-aux tyvars context)
- ;; This computes a signature for the datatype as a whole.
- (let ((gtype (ast->gtype context simple)))
- ;; This sets the signatures for the constructors
- (dolist (con constr-defs)
- (let* ((con-type (**arrow-type/l (append (con-types con)
- (list simple))))
- (con-context (restrict-context
- context (tuple-2-2 (assq con all-con-vars))))
- (con-signature (ast->gtype con-context con-type)))
- (setf (con-signature con) con-signature)))
- (update-slots algdata def
- (n-constr (length constrs))
- (constrs constr-defs)
- (context context)
- (tyvars tyvars)
- (signature gtype)
- (classes '())
- (enum? enum?)
- (tuple? (and (not (null? constrs)) (null? (cdr constrs))))
- (real-tuple? '#f)
- (deriving derived-classes)
- ))
- (setf (algdata-runtime-var def)
- (make-runtime-var def "-type" (core-symbol "DataType")))
- (process-alg-annotations def)
- def))))
-
-
- (define (process-alg-strictness-annotation anns)
- (let ((res '#f))
- (dolist (a anns)
- (if (and (annotation-value? a)
- (eq? (annotation-value-name a) '|STRICT|)
- (null? (annotation-value-args a)))
- (setf res '#t)
- (signal-unknown-annotation a)))
- res))
-
- (define (get-constr-strictness anns all-strict?)
- (let ((res all-strict?))
- (dolist (a anns)
- (cond ((annotation-value? a)
- (if (and (eq? (annotation-value-name a) '|STRICT|)
- (null? (annotation-value-args a)))
- (setf res '#t)
- (signal-unknown-annotation a)))
- (else (signal-unknown-annotation a))))
- res))
-
- (define (process-alg-annotations alg)
- (dolist (a (module-annotations *module*))
- (when (and (annotation-value? a)
- (or (eq? (annotation-value-name a) '|ImportLispType|)
- (eq? (annotation-value-name a) '|ExportLispType|))
- (assq (def-name alg) (car (annotation-value-args a))))
- (if (eq? (annotation-value-name a) '|ImportLispType|)
- (setf (algdata-implemented-by-lisp? alg) '#t)
- (setf (algdata-export-to-lisp? alg) '#t))
- (let ((constrs (tuple-2-2 (assq (def-name alg)
- (car (annotation-value-args a))))))
- (dolist (c constrs)
- (process-annotated-constr
- alg
- (lookup-alg-constr (tuple-2-1 c) (algdata-constrs alg))
- (tuple-2-2 c)))))))
-
- (define (lookup-alg-constr name constrs)
- (if (null? constrs)
- (fatal-error 'bad-constr-name "Constructor ~A not in algdata~%"
- name)
- (if (eq? name (def-name (car constrs)))
- (car constrs)
- (lookup-alg-constr name (cdr constrs)))))
-
- (define (process-annotated-constr alg con lisp-fns)
- ;; For nullary tuples, allow a single annotation to represent a constant
- ;; and generate the test function by default.
- (when (and (eqv? (con-arity con) 0)
- lisp-fns
- (null? (cdr lisp-fns)))
- (push `(lambda (x) (eq? x ,(car lisp-fns))) lisp-fns))
- ;; Insert an implicit test function for tuples (never used anyway!)
- (when (and (algdata-tuple? alg)
- (eqv? (+ 1 (con-arity con)) (length lisp-fns)))
- (push '(lambda (x) '#t) lisp-fns))
- (when (or (not (null? (con-lisp-fns con)))
- (not (eqv? (length lisp-fns) (+ 2 (con-arity con)))))
- (fatal-error 'bad-constr-annotation
- "Bad annotation for ~A in ~A~%" con alg))
- (setf (con-lisp-fns con) lisp-fns))
-
- ;;; This should be obsolete - the parser now checks annotations thoroughly.
-
- (define (signal-unknown-annotation a)
- (recoverable-error 'bad-annotation "Bad or misplaced annotation: ~A%"
- a))
-
- (define (restrict-context context vars)
- (if (null? context)
- '()
- (let ((rest (restrict-context (cdr context) vars)))
- (if (memq (context-tyvar (car context)) vars)
- (cons (car context) rest)
- rest))))
-
- (define (signal-bad-algdata-tyvar tyvar)
- (phase-error 'bad-algdata-tyvar
- "Only type variables defined by the left hand side of a data declaration~%~
- may be used on the right side. Type variable ~a is can not be used on~%~
- the right side of this data declaration."
- tyvar))
-
- (define (signal-unreferenced-tyvar-arg tyvar)
- (phase-error 'unreferenced-tyvar-arg
- "Type variable ~a is defined by the left hand side of a data declaration~%~
- but is not referenced on the right hand side."
- tyvar))
-
- ;;; Synonyms
-
- ;;; Errors detected:
-
- (define (synonym->def synonym-decl)
- (remember-context synonym-decl
- (with-slots synonym-decl (simple body) synonym-decl
- (let* ((def (tycon-def simple))
- (tyvars (simple-tyvar-list simple))
- (tyvars-referenced (resolve-type body)))
- (dolist (v tyvars)
- (if (not (memq v tyvars-referenced))
- (signal-unreferenced-synonym-arg v)))
- (dolist (v tyvars-referenced)
- (if (not (memq v tyvars))
- (signal-bad-synonym-tyvar v)))
- (update-slots synonym def
- (args tyvars)
- (body body))
- (push (cons def (gather-synonyms body '())) *synonym-refs*)
- def))))
-
- (define (signal-bad-synonym-tyvar tyvar)
- (phase-error 'bad-synonym-tyvar
- "The variable ~a is referenced on the right hand side of a type synonym~%~
- declaration but is not bound by the left hand side."
- tyvar))
-
- (define (signal-unreferenced-synonym-arg tyvar)
- (haskell-warning 'unreferenced-synonym-arg
- "The variable ~a is bound by the left hand side of a type synonym declaration~%~
- but is not referenced on the right hand side."
- tyvar))
-
- (define (gather-synonyms type acc)
- (cond ((tyvar? type)
- acc)
- ((and (synonym? (tycon-def type))
- (eq? *unit* (def-unit (tycon-def type))))
- (gather-synonyms/list (tycon-args type)
- (cons (tycon-def type) acc)))
- (else
- (gather-synonyms/list (tycon-args type) acc))))
-
- (define (gather-synonyms/list types acc)
- (if (null? types)
- acc
- (gather-synonyms/list (cdr types) (gather-synonyms (car types) acc))))
-